#include <cstring>

#include "src/CmdParser.h"

namespace czj {
namespace util {

static CmdParser *cNew(const char *_cmd);
static void cDelete(CmdParser *_this);
static void cConstruct(CmdParser *_this, const char *_cmd);
static void cDestruct(CmdParser *_this);
static void cBindHelpKey(CmdParser *_this, const char *_key);
static bool cAddBool(CmdParser *_this, int _id, const char *_describe);
static bool cBindBoolKey(CmdParser *_this, int _id, const char *_key);
static bool cGetBool(CmdParser *_this, int _id);
static bool cAddVariable(CmdParser *_this, int _id, const char *_describe, bool _nullable);
static bool cBindVariableKey(CmdParser *_this, int _id, const char *_key, const char *_hint);
static bool cBindVariableExpression(CmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default);
static const char *cGetVariable(CmdParser *_this, int _id);
static bool cAddList(CmdParser *_this, int _id, const char *_describe, bool _nullable);
static bool cBindListKey(CmdParser *_this, int _id, const char *_key, const char *_hint);
static bool cBindListExpression(CmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default);
static bool cGetList(CmdParser *_this, int _id, const char **_buf, size_t _size);
static void cAddOperand(CmdParser *_this, int _id, const char *_describe, const char *_hint);
static const char *cGetOperand(CmdParser *_this, int _id);
static void cEnableExtension(CmdParser *_this, const char *_describe, const char *_hint);
static bool cGetExtension(CmdParser *_this, const char **_buf, size_t _len);
static void cHelp(CmdParser *_this);
static bool cParse(CmdParser *_this, int _length, const char *const *_arguments);

CmdParser *cNew(const char *_cmd) {
	CmdParser *cmdParser = (CmdParser *) new char[sizeof(CmdParser)];
	cConstruct(cmdParser, _cmd);
	return cmdParser;
}

void cDelete(CmdParser *_this) {
	cDestruct(_this);
	delete[] (char *) _this;
}

void cConstruct(CmdParser *_this, const char *_cmd) {
	new(_this) CmdParser(_cmd);
}

void cDestruct(CmdParser *_this) {
	_this->~CmdParser();
}

void cBindHelpKey(CmdParser *_this, const char *_key) {
	_this->bindHelpKey(_key);
}

bool cAddBool(CmdParser *_this, int _id, const char *_describe) {
	return _this->addBool(_id, _describe);
}

bool cBindBoolKey(CmdParser *_this, int _id, const char *_key) {
	return _this->bindBoolKey(_id, _key);
}

bool cGetBool(CmdParser *_this, int _id) {
	return _this->getBool(_id);
}

bool cAddVariable(CmdParser *_this, int _id, const char *_describe, bool _nullable) {
	return _this->addVariable(_id, _describe, _nullable);
}

bool cBindVariableKey(CmdParser *_this, int _id, const char *_key, const char *_hint) {
	return _this->bindVariableKey(_id, _key, _hint);
}

bool cBindVariableExpression(CmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default) {
	return _this->bindVariableExpression(_id, _key, _operator, _hint, _default);
}

const char *cGetVariable(CmdParser *_this, int _id) {
	return _this->getVariable(_id).c_str();
}

bool cAddList(CmdParser *_this, int _id, const char *_describe, bool _nullable) {
	return _this->addList(_id, _describe, _nullable);
}

bool cBindListKey(CmdParser *_this, int _id, const char *_key, const char *_hint) {
	return _this->bindListKey(_id, _key, _hint);
}

bool cBindListExpression(CmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default) {
	return _this->bindListExpression(_id, _key, _operator, _hint, _default);
}

bool cGetList(CmdParser *_this, int _id, const char **_buf, size_t _size) {
	size_t i = 0;
	for (auto const &value : _this->getList(_id)) {
		if (i >= _size) {
			return false;
		}
		_buf[i] = value.c_str();
		++i;
	}
	memset(_buf + i, 0, _size);
	return true;
}

void cAddOperand(CmdParser *_this, int _id, const char *_describe, const char *_hint) {
	return _this->addOperand(_id, _describe, _hint);
}

const char *cGetOperand(CmdParser *_this, int _id) {
	return _this->getOperand(_id).c_str();
}

void cEnableExtension(CmdParser *_this, const char *_describe, const char *_hint) {
	return _this->enableExtension(_describe, _hint);
}

bool cGetExtension(CmdParser *_this, const char **_buf, size_t _size) {
	size_t i = 0;
	for (auto const &value : _this->getExtension()) {
		if (i >= _size) {
			return false;
		}
		_buf[i] = value.c_str();
		++i;
	}
	memset(_buf + i, 0, _size);
	return true;
}

void cHelp(CmdParser *_this) {
	_this->help();
}

bool cParse(CmdParser *_this, int _length, const char *const *_arguments) {
	return _this->parse(_length, _arguments);
}

} // util
} // czj

#ifdef __cplusplus
extern "C" {

using namespace czj::util;

typedef CmdParser CCmdParser;

CCmdParser *cCmdParserNew(const char *_cmd);
void cCmdParserDelete(CCmdParser *_this);
void cCmdParserConstruct(CCmdParser *_this, const char *_cmd);
void cCmdParserDestruct(CCmdParser *_this);
void cCmdParserBindHelpKey(CCmdParser *_this, const char *_key);
bool cCmdParserAddBool(CCmdParser *_this, int _id, const char *_describe);
bool cCmdParserBindBoolKey(CCmdParser *_this, int _id, const char *_key);
bool cCmdParserGetBool(CCmdParser *_this, int _id);
bool cCmdParserAddVariable(CCmdParser *_this, int _id, const char *_describe, bool _nullable);
bool cCmdParserBindVariableKey(CCmdParser *_this, int _id, const char *_key, const char *_hint);
bool cCmdParserBindVariableExpression(CCmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default);
const char *cCmdParserGetVariable(CCmdParser *_this, int _id);
bool cCmdParserAddList(CCmdParser *_this, int _id, const char *_describe, bool _nullable);
bool cCmdParserBindListKey(CCmdParser *_this, int _id, const char *_key, const char *_hint);
bool cCmdParserBindListExpression(CCmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default);
bool cCmdParserGetList(CCmdParser *_this, int _id, const char **_buf, size_t _size);
void cCmdParserAddOperand(CCmdParser *_this, int _id, const char *_describe, const char *_hint);
const char *cCmdParserGetOperand(CCmdParser *_this, int _id);
void cCmdParserEnableExtension(CCmdParser *_this, const char *_describe, const char *_hint);
bool cCmdParserGetExtension(CCmdParser *_this, const char **_buf, size_t _size);
void cCmdParserHelp(CCmdParser *_this);
bool cCmdParserParse(CCmdParser *_this, int _length, const char *const *_arguments);

CCmdParser *cCmdParserNew(const char *_cmd) {
	return cNew(_cmd);
}

void cCmdParserDelete(CCmdParser *_this) {
	cDelete(_this);
}

void cCmdParserConstruct(CCmdParser *_this, const char *_cmd) {
	cConstruct(_this, _cmd);
}

void cCmdParserDestruct(CCmdParser *_this) {
	cDestruct(_this);
}

void cCmdParserBindHelpKey(CCmdParser *_this, const char *_key) {
	cBindHelpKey(_this, _key);
}

bool cCmdParserAddBool(CCmdParser *_this, int _id, const char *_describe) {
	return cAddBool(_this, _id, _describe);
}

bool cCmdParserBindBoolKey(CCmdParser *_this, int _id, const char *_key) {
	return cBindBoolKey(_this, _id, _key);
}

bool cCmdParserGetBool(CCmdParser *_this, int _id) {
	return cGetBool(_this, _id);
}

bool cCmdParserAddVariable(CCmdParser *_this, int _id, const char *_describe, bool _nullable) {
	return cAddVariable(_this, _id, _describe, _nullable);
}

bool cCmdParserBindVariableKey(CCmdParser *_this, int _id, const char *_key, const char *_hint) {
	return cBindVariableKey(_this, _id, _key, _hint);
}

bool cCmdParserBindVariableExpression(CCmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default) {
	return cBindVariableExpression(_this, _id, _key, _operator, _hint, _default);
}

const char *cCmdParserGetVariable(CCmdParser *_this, int _id) {
	return cGetVariable(_this, _id);
}

bool cCmdParserAddList(CCmdParser *_this, int _id, const char *_describe, bool _nullable) {
	return cAddList(_this, _id, _describe, _nullable);
}

bool cCmdParserBindListKey(CCmdParser *_this, int _id, const char *_key, const char *_hint) {
	return cBindListKey(_this, _id, _key, _hint);
}

bool cCmdParserBindListExpression(CCmdParser *_this, int _id, const char *_key, const char *_operator, const char *_hint, const char *_default) {
	return cBindListExpression(_this, _id, _key, _operator, _hint, _default);
}

bool cCmdParserGetList(CCmdParser *_this, int _id, const char **_buf, size_t _size) {
	return cGetList(_this, _id, _buf, _size);
}

void cCmdParserAddOperand(CCmdParser *_this, int _id, const char *_describe, const char *_hint) {
	return cAddOperand(_this, _id, _describe, _hint);
}

const char *cCmdParserGetOperand(CCmdParser *_this, int _id) {
	return cGetOperand(_this, _id);
}

void cCmdParserEnableExtension(CCmdParser *_this, const char *_describe, const char *_hint) {
	return cEnableExtension(_this, _describe, _hint);
}

bool cCmdParserGetExtension(CCmdParser *_this, const char **_buf, size_t _size) {
	return cGetExtension(_this, _buf, _size);
}

void cCmdParserHelp(CCmdParser *_this) {
	cHelp(_this);
}

bool cCmdParserParse(CCmdParser *_this, int _length, const char *const *_arguments) {
	return cParse(_this, _length, _arguments);
}

}

#endif
